package com.gitee.wsl.mathematics.matrix.mat3

import com.gitee.wsl.ext.array.DoubleArray
import com.gitee.wsl.io.dataproxy.DataProxy
import com.gitee.wsl.io.dataproxy.asProxy
import com.gitee.wsl.mathematics.matrix.M
import com.gitee.wsl.mathematics.matrix.MatCopyInitializer
import com.gitee.wsl.mathematics.matrix.MatInitializer
import com.gitee.wsl.mathematics.matrix.N
import com.gitee.wsl.mathematics.matrix.mat2.MutableMat2
import com.gitee.wsl.mathematics.matrix.mat2.MutableMatrix2
import com.gitee.wsl.mathematics.matrix.mat4.MutableMat4
import com.gitee.wsl.mathematics.matrix.mat4.MutableMat4.Companion

import com.gitee.wsl.mathematics.vector.vec2.MutableVec2
import com.gitee.wsl.mathematics.vector.vec3.MutableVec3
import com.gitee.wsl.mathematics.vector.vec3.Vec3

class MutableMat3(m00: Double=0.0, m01: Double=0.0,m02: Double=0.0,
                  m10: Double=0.0, m11: Double=0.0,m12: Double=0.0,
                  m20: Double=0.0, m21: Double=0.0,m22: Double=0.0,
                  override val proxy: DataProxy<Double> =
                      DoubleArray(
                          m00, m01, m02,
                          m10, m11, m12,
                          m20, m21, m22).asProxy())
    :Mat3(proxy = proxy),MutableMatrix3D<Mat3, Vec3> {
    constructor(other: Matrix3D<*, *>):this(
        other.m00, other.m01,other.m02,
        other.m10, other.m11,other.m12,
        other.m20, other.m21,other.m22)
    constructor(initializer: MatInitializer<Double>):this(
        initializer(0,0),initializer(0,1),initializer(0,2),
        initializer(1,0),initializer(1,1),initializer(1,2),
        initializer(2,0),initializer(2,1),initializer(2,2)
        )

    override val self
        get() = this

    override val m by lazy{listOf(M[0], M[1],M[2])}

    override val n by lazy {listOf(N[0], N[1],N[2])}

    override fun copy(block: MatCopyInitializer<Double>) = MutableMat3 { i, j->
        this[i,j].block(i,j)
    }

    //override fun createVec(indexRage:IntRange) = createVec(indexRage.toList())

    override fun createVec2(x: Double, y: Double) = MutableVec2(x,y)

    override fun createMat2(block: (MutableMatrix2<Double, *, *>) -> Unit): MutableMat2 {
        val ret = MutableMat2()
        block(ret)
        return ret
    }

    override fun createVec(indexes: List<Int>) = MutableVec3(proxy = proxy.asProxy(indexes))

    override fun create(m00: Double, m01: Double,m02: Double,
                        m10: Double, m11: Double,m12: Double,
                        m20: Double, m21: Double,m22: Double)
            =   MutableMat3(m00, m01, m02,
                            m10, m11, m12,
                            m20, m21, m22)

    override fun toMutable() = this

    override operator fun M.get(row: Int) = createVec(rowIndexes(row))

    override operator fun N.get(col: Int) = createVec(colIndexes(col))

    companion object{
        val IDENTITY  = identity()

        fun identity()= MutableMat3(
            1.0, 0.0, 0.0, 
            0.0, 1.0, 0.0, 
            0.0, 0.0, 1.0
        )
    }
}